home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / SAVE.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  21KB  |  865 lines

  1. /*    SCCS Id: @(#)save.c    3.0    89/04/13
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #define MONATTK_H    /* comment line for pre-compiled headers */
  6. /* block some unused #defines to avoid overloading some cpp's */
  7. #include "hack.h"
  8. #include "lev.h"
  9.  
  10. #ifdef WORM
  11. #include "wseg.h"
  12. #endif
  13.  
  14. #ifndef NO_SIGNAL
  15. #include <signal.h>
  16. #endif /* !NO_SIGNAL */
  17. #if defined(EXPLORE_MODE) && !defined(LSC) && !defined(O_WRONLY) && !defined(AZTEC_C)
  18. #include <fcntl.h>
  19. #endif /* EXPLORE_MODE */
  20.  
  21. boolean hu;        /* set during hang-up */
  22.  
  23. #ifdef DGK
  24. struct finfo fileinfo[MAXLEVEL+1];
  25. long bytes_counted;
  26. int count_only;
  27. #else
  28. boolean level_exists[MAXLEVEL+1];
  29. #endif
  30.  
  31. #ifdef ZEROCOMP
  32. static void FDECL(bputc, (UCHAR_P));
  33. #endif
  34. static void FDECL(saveobjchn, (int,struct obj *));
  35. static void FDECL(savemonchn, (int,struct monst *));
  36. static void FDECL(savegoldchn, (int,struct gold *));
  37. static void FDECL(savetrapchn, (int,struct trap *));
  38. static void FDECL(savegenoinfo, (int));
  39. #ifdef DGK
  40. static void FDECL(savelev0, (int,XCHAR_P));
  41. static boolean NDECL(swapout_oldest);
  42. static void FDECL(copyfile, (char *,char *));
  43. #endif /* DGK */
  44. static void FDECL(spill_objs, (struct obj *));
  45. #ifdef __GNULINT__
  46. static long nulls[10];
  47. #else
  48. #define nulls nul
  49. #endif
  50.  
  51. int
  52. dosave(){
  53.     clrlin();
  54. #ifdef MACOS
  55.     if(!flags.silent) SysBeep(1);
  56.     if(UseMacAlertText(128, "Really save ?") != 1) {
  57. #else
  58.     pline("Really save? ");    /* especially useful if COMPRESS defined */
  59.     if(yn() == 'n') {
  60. #endif
  61.         clrlin();
  62.         (void) fflush(stdout);
  63.         if(multi > 0) nomul(0);
  64.     } else {
  65.         clear_screen();
  66.         (void) fflush(stdout);
  67.         hu = FALSE;
  68.         if(dosave0()) {
  69.             settty("Be seeing you...\n");
  70.             exit(0);
  71.         } else (void)doredraw();
  72.     }
  73.     return 0;
  74. }
  75.  
  76. #ifndef NOSAVEONHANGUP
  77. int
  78. hangup(){
  79.     if (!hu)
  80.     {
  81.         hu = TRUE;
  82.         (void) dosave0();
  83. # ifndef VMS
  84.         exit(1);
  85. # endif
  86.     }
  87.     return 0;
  88. }
  89. #endif
  90.  
  91. /* returns 1 if save successful */
  92. int
  93. dosave0() {
  94.     register int fd, ofd;
  95.     int tmp;        /* not register ! */
  96.     xchar ltmp;
  97. #ifdef DGK
  98.     long fds, needed;
  99.     int mode;
  100. #endif
  101. #ifdef COMPRESS
  102.     char    cmd[80];
  103. #endif
  104. #ifdef MACOS
  105.     short    savenum;
  106. #endif
  107.  
  108.     if (!SAVEF[0])
  109.         return 0;
  110.  
  111. #if defined(UNIX) || defined(VMS)
  112.     (void) signal(SIGHUP, SIG_IGN);
  113. #endif
  114. #if !defined(__TURBOC__) && !defined(NO_SIGNAL)
  115.     (void) signal(SIGINT, SIG_IGN);
  116. #endif
  117.  
  118. #ifdef MSDOS
  119. # ifdef DGK
  120.     if(!hu && !saveDiskPrompt(0))    return 0;
  121. # endif
  122. # ifdef EXPLORE_MODE
  123.     if(!hu) {
  124. #  ifdef AMIGA_WBENCH
  125.         (fd = ami_wbench_getsave(O_RDONLY));
  126. #  else
  127.         (fd = open(SAVEF, O_RDONLY));
  128. #  endif
  129.         if (fd > 0) {
  130.         (void) close(fd);
  131.         clrlin();
  132.         pline("There seems to be an old save file.  Overwrite it? ");
  133.         if (yn() == 'n') return 0;
  134.         }
  135.     }
  136. # endif
  137. # ifdef TOS
  138.     fd = creat(SAVEF, FCMASK);
  139. # else
  140. #  ifdef AMIGA_WBENCH
  141.     fd=ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC);
  142. #  else
  143.     (fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK));
  144. #  endif
  145. # endif
  146. #else /* MSDOS */
  147. # ifdef EXPLORE_MODE
  148.     if(!hu) {
  149.         fd = open(SAVEF, O_RDONLY);
  150.         if (fd > 0) {
  151.         (void) close(fd);
  152.         clrlin();
  153.         pline("There seems to be an old save file.  Overwrite it? ");
  154.         if (yn() == 'n') return 0;
  155.         }
  156.     }
  157. # endif
  158. # ifdef MACOS
  159.     {
  160.         Str255    fileName;
  161.         OSErr    er;
  162.         struct term_info    *t;
  163.         extern WindowPtr    HackWindow;
  164.         
  165.         t = (term_info *)GetWRefCon(HackWindow);
  166.         (void)GetVol(&fileName,&tmp);    /* tmp is old volume */
  167.         (void)SetVol(0L, savenum = t->recordVRefNum);    /* savenum is used below */
  168.         Strcpy((char *)&fileName[1], SAVEF);
  169.         fileName[0] = strlen(SAVEF);
  170.  
  171.         if (er = Create(&fileName, 0, CREATOR, discover ? EXPLORE_TYPE : SAVE_TYPE))
  172.             SysBeep(1);
  173.         fd = open(SAVEF, O_WRONLY | O_BINARY);
  174.         (void)SetVol(0L, t->system.sysVRefNum);
  175.     }
  176. # else
  177.     fd = creat(SAVEF, FCMASK);
  178. # endif /* MACOS */
  179. #endif /* MSDOS */
  180.     if(fd < 0) {
  181.         if(!hu) pline("Cannot open save file.");
  182. #ifdef AMIGA_WBENCH
  183.         ami_wbench_unlink(SAVEF);
  184. #endif
  185. #ifdef MACOS
  186.         (void)SetVol(0L, savenum);
  187. #endif
  188.         (void) unlink(SAVEF);        /* ab@unido */
  189. #ifdef MACOS
  190.         (void)SetVol(0L, tmp);
  191. #endif
  192.         return(0);
  193.     }
  194.     if(flags.moonphase == FULL_MOON)    /* ut-sally!fletcher */
  195.         change_luck(-1);        /* and unido!ab */
  196.     home();
  197.     cl_end();
  198. #ifdef DGK
  199.     if(!hu) msmsg("Saving: ");
  200.     mode = COUNT;
  201. again:
  202.     savelev(fd, dlevel, mode);
  203.     /* count_only will be set properly by savelev */
  204. #else
  205. # ifdef MACOS
  206.     printf("Saving: ");
  207. # endif
  208.     savelev(fd,dlevel);
  209. #endif
  210.     saveobjchn(fd, invent);
  211.     savemonchn(fd, fallen_down);
  212.     savegenoinfo(fd);
  213.     tmp = getuid();
  214.     bwrite(fd, (genericptr_t) &tmp, sizeof tmp);
  215.     bwrite(fd, (genericptr_t) &flags, sizeof(struct flag));
  216.     bwrite(fd, (genericptr_t) &dlevel, sizeof dlevel);
  217.     bwrite(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel);
  218.     bwrite(fd, (genericptr_t) &moves, sizeof moves);
  219.     bwrite(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
  220.     bwrite(fd, (genericptr_t) &wiz_level, sizeof wiz_level);
  221.     bwrite(fd, (genericptr_t) &medusa_level, sizeof medusa_level);
  222.     bwrite(fd, (genericptr_t) &bigroom_level, sizeof bigroom_level);
  223. #ifdef ORACLE
  224.     bwrite(fd, (genericptr_t) &oracle_level, sizeof oracle_level);
  225. #endif
  226. #ifdef REINCARNATION
  227.     bwrite(fd, (genericptr_t) &rogue_level, sizeof rogue_level);
  228. #endif
  229. #ifdef STRONGHOLD
  230.     bwrite(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level);
  231.     bwrite(fd, (genericptr_t) &tower_level, sizeof tower_level);
  232.     bwrite(fd, (genericptr_t) tune, sizeof tune);
  233. #  ifdef MUSIC
  234.     bwrite(fd, (genericptr_t) &music_heard, sizeof music_heard);
  235. #  endif
  236. #endif
  237.     bwrite(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev);
  238.     bwrite(fd, (genericptr_t) &u, sizeof(struct you));
  239. #ifdef SPELLS
  240.     bwrite(fd, (genericptr_t) spl_book, 
  241.                 sizeof(struct spell) * (MAXSPELL + 1));
  242. #endif
  243. #ifdef NAMED_ITEMS
  244.     bwrite(fd, (genericptr_t) artiexist, 
  245.                 (unsigned)(sizeof(boolean) * artifact_num));
  246. #endif
  247.     if(u.ustuck)
  248.         bwrite(fd, (genericptr_t) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
  249.     bwrite(fd, (genericptr_t) pl_character, sizeof pl_character);
  250. #ifdef TUTTI_FRUTTI
  251.     bwrite(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
  252.     bwrite(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit);
  253.     savefruitchn(fd);
  254. #endif
  255.     savenames(fd);
  256. #ifdef DGK
  257.     if (mode == COUNT) {
  258. # ifdef ZEROCOMP
  259.         bflush(fd);
  260. # endif
  261.         /* make sure there is enough disk space */
  262.         needed = bytes_counted;
  263.         for (ltmp = 1; ltmp <= maxdlevel; ltmp++)
  264.             if (ltmp != dlevel && fileinfo[ltmp].where)
  265.                 needed += fileinfo[ltmp].size + (sizeof ltmp);
  266. #ifdef AMIGA_WBENCH
  267.         needed+=ami_wbench_iconsize(SAVEF);
  268. #endif
  269.         fds = freediskspace(SAVEF);
  270.         if(needed > fds) {
  271.             if(!hu) {
  272.             pline("There is insufficient space on SAVE disk.");
  273.             pline("Require %ld bytes but only have %ld.", needed,
  274.                 fds);
  275.             }
  276.             flushout();
  277. #ifdef AMIGA_WBENCH
  278.             ami_wbench_unlink(SAVEF);
  279. #endif
  280.             (void) close(fd);
  281.             (void) unlink(SAVEF);
  282.             return 0;
  283.         }
  284.         mode = WRITE;
  285.         goto again;
  286.     }
  287. #endif
  288.     for(ltmp = (xchar)1; ltmp <= maxdlevel; ltmp++) {
  289. #ifdef DGK
  290.         if (ltmp == dlevel || !fileinfo[ltmp].where) continue;
  291.         if (fileinfo[ltmp].where != ACTIVE)
  292.             swapin_file(ltmp);
  293. #else
  294.         if(ltmp == dlevel || !level_exists[ltmp]) continue;
  295. #endif
  296.         glo(ltmp);
  297. #if defined(DGK) || defined(MACOS)
  298. # ifdef MACOS
  299. #define msmsg printf
  300. # endif
  301.         if(!hu) msmsg(".");
  302. #endif
  303.         if((ofd = open(lock, OMASK)) < 0) {
  304.             if(!hu) pline("Error while saving: cannot read %s.", lock);
  305.             (void) close(fd);
  306. #ifdef MACOS
  307.             (void)SetVol(0L, savenum);
  308. #endif
  309.             (void) unlink(SAVEF);
  310. #ifdef MACOS
  311.             (void)SetVol(0L, tmp);
  312. #endif
  313. #ifdef AMIGA_WBENCH
  314.             ami_wbench_unlink(SAVEF);
  315. #endif
  316.             if(!hu) done(TRICKED);
  317.             return(0);
  318.         }
  319. #ifdef ZEROCOMP
  320.         minit();
  321. #endif
  322.         getlev(ofd, hackpid, ltmp, FALSE);
  323.         (void) close(ofd);
  324.         bwrite(fd, (genericptr_t) <mp, sizeof ltmp);  /* level number */
  325. #ifdef DGK
  326.         savelev(fd, ltmp, WRITE);            /* actual level */
  327. #else
  328.         savelev(fd, ltmp);            /* actual level */
  329. #endif
  330.         (void) unlink(lock);
  331.     }
  332. #ifdef ZEROCOMP
  333.     bflush(fd);
  334. #endif
  335.     (void) close(fd);
  336.     glo(dlevel);
  337.     (void) unlink(lock);    /* get rid of current level --jgm */
  338.     glo(0);
  339.     (void) unlink(lock);
  340. #ifdef COMPRESS
  341.     Strcpy(cmd, COMPRESS);
  342.     Strcat(cmd, " ");
  343. # ifdef COMPRESS_OPTIONS
  344.     Strcat(cmd, COMPRESS_OPTIONS);
  345.     Strcat(cmd, " ");
  346. # endif
  347.     Strcat(cmd, SAVEF);
  348.     (void) system(cmd);
  349. #endif
  350. #ifdef AMIGA_WBENCH
  351.     ami_wbench_iconwrite(SAVEF);
  352. #endif
  353. #ifdef MACOS
  354.     (void)SetVol(0L, tmp);
  355. #endif
  356.     return(1);
  357. }
  358.  
  359. #ifdef DGK
  360. boolean
  361. savelev(fd, lev, mode)
  362. int fd;
  363. xchar lev;
  364. int mode;
  365. {
  366.     if (mode & COUNT) {
  367. # ifdef ZEROCOMP /* should be superfluous */
  368.         if (!count_only)    /* did we just write? */
  369.             bflush(0);
  370.         /*dbg();*/
  371. # endif
  372.         count_only = TRUE;
  373.         bytes_counted = 0;
  374.         savelev0(fd, lev);
  375.         while (bytes_counted > freediskspace(levels))
  376.             if (!swapout_oldest())
  377.                 return FALSE;
  378.     }
  379.     if (mode & WRITE) {
  380. # ifdef ZEROCOMP
  381.         if (mode & COUNT)    /* did we just count? */
  382.             bflush(fd);
  383. # endif
  384.         count_only = FALSE;
  385.         bytes_counted = 0;
  386.         savelev0(fd, lev);
  387.     }
  388.     fileinfo[lev].where = ACTIVE;
  389.     fileinfo[lev].time = moves;
  390.     fileinfo[lev].size = bytes_counted;
  391.     return TRUE;
  392. }
  393.  
  394. static
  395. void
  396. savelev0(fd,lev)
  397. #else
  398. void
  399. savelev(fd,lev)
  400. #endif
  401. int fd;
  402. xchar lev;
  403. {
  404. #ifdef WORM
  405.     register struct wseg *wtmp, *wtmp2;
  406.     register int tmp;
  407. #endif
  408. #ifdef TOS
  409.     short tlev;
  410. #endif
  411.  
  412.     if(fd < 0) panic("Save on bad file!");    /* impossible */
  413. #ifndef DGK
  414.     if(lev >= 0 && lev <= MAXLEVEL)
  415.         level_exists[lev] = TRUE;
  416. #endif
  417.     bwrite(fd,(genericptr_t) &hackpid,sizeof(hackpid));
  418. #ifdef TOS
  419.     tlev=lev; tlev &= 0x00ff;
  420.     bwrite(fd,(genericptr_t) &tlev,sizeof(tlev));
  421. #else
  422.     bwrite(fd,(genericptr_t) &lev,sizeof(lev));
  423. #endif
  424. #if defined(SMALLDATA) && defined(MACOS)
  425.     /* asssumes ROWNO*sizeof(struct rm) < 128 bytes */
  426.     {
  427.         short    i;
  428.         char    length;
  429.         char    bufr[256],*ptr,*src,*d,*p;
  430.         
  431.         d = calloc(ROWNO*COLNO, sizeof(struct rm));
  432.         p = d;
  433.         for (i = 0; i < COLNO; i++) {
  434.             ptr = &bufr[0];
  435.             src = (char *)&levl[i][0];
  436.             PackBits(&src, &ptr, ROWNO * sizeof(struct rm));
  437.             length = (char)(ptr - &bufr[0]);
  438.             BlockMove(&length, p++, (Size)1);
  439.             BlockMove(bufr, p, (Size)length);
  440.             p += (long)length;
  441.         }
  442.         i = (short)(p - d);
  443.         bwrite(fd, (genericptr_t)&i, sizeof(short));
  444.         bwrite(fd, (genericptr_t)d, i);
  445.         free(d);
  446.     }
  447. #else
  448.     bwrite(fd,(genericptr_t) levl,sizeof(levl));
  449. #endif /* SMALLDATA */
  450. #ifdef REINCARNATION
  451.     if(dlevel == rogue_level && lev != rogue_level)
  452.         /* save the symbols actually used to represent the level, not
  453.          * those in use for the current level (the default symbols used
  454.          * for rogue), since we will need to know whether to update
  455.          * the display of the screen when the game is restored under
  456.          * a potentially different value of showsyms from the
  457.          * environment */
  458.         /* if a game is saved while not on rogue level, the usual
  459.          * showsyms will be written out for the rogue level too, but
  460.          * they will be ignored on restore so it doesn't matter */
  461.         bwrite(fd, (genericptr_t) savesyms, sizeof savesyms);
  462.     else
  463. #endif
  464.         bwrite(fd, (genericptr_t) showsyms, sizeof showsyms);
  465.     bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves));
  466.     bwrite(fd,(genericptr_t) &xupstair,sizeof(xupstair));
  467.     bwrite(fd,(genericptr_t) &yupstair,sizeof(yupstair));
  468.     bwrite(fd,(genericptr_t) &xdnstair,sizeof(xdnstair));
  469.     bwrite(fd,(genericptr_t) &ydnstair,sizeof(ydnstair));
  470. #ifdef STRONGHOLD
  471.     bwrite(fd,(genericptr_t) &xupladder,sizeof(xupladder));
  472.     bwrite(fd,(genericptr_t) &yupladder,sizeof(yupladder));
  473.     bwrite(fd,(genericptr_t) &xdnladder,sizeof(xdnladder));
  474.     bwrite(fd,(genericptr_t) &ydnladder,sizeof(ydnladder));
  475. #endif
  476.     bwrite(fd,(genericptr_t) &fountsound,sizeof(fountsound));
  477.     bwrite(fd,(genericptr_t) &sinksound,sizeof(sinksound));
  478.     savemonchn(fd, fmon);
  479.     savegoldchn(fd, fgold);
  480.     savetrapchn(fd, ftrap);
  481.  
  482.     saveobjchn(fd, fobj);
  483.     saveobjchn(fd, billobjs);
  484.  
  485.     save_engravings(fd);
  486.     bwrite(fd,(genericptr_t) rooms,sizeof(rooms));
  487.     bwrite(fd,(genericptr_t) doors,sizeof(doors));
  488. #ifdef WORM
  489.     bwrite(fd,(genericptr_t) wsegs,sizeof(wsegs));
  490.     for(tmp=1; tmp<32; tmp++){
  491.         for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){
  492.             wtmp2 = wtmp->nseg;
  493.             bwrite(fd,(genericptr_t) wtmp,sizeof(struct wseg));
  494. #ifdef DGK
  495.             if (!count_only)
  496. #endif
  497.                 free((genericptr_t) wtmp);
  498.         }
  499. #ifdef DGK
  500.         if (!count_only)
  501. #endif
  502.             wsegs[tmp] = 0;
  503.     }
  504.     bwrite(fd,(genericptr_t) wgrowtime,sizeof(wgrowtime));
  505. #endif /* WORM /**/
  506. #ifdef DGK
  507.     if (count_only)    return;
  508. #endif
  509.     billobjs = 0;
  510.     fgold = 0;
  511.     ftrap = 0;
  512.     fmon = 0;
  513.     fobj = 0;
  514. }
  515.  
  516. #ifdef ZEROCOMP
  517.  
  518. #define RLESC '\0'    /* Leading character for run of LRESC's */
  519. #define flushoutrun(ln) bputc(RLESC); bputc(ln); ln = -1;
  520.  
  521. static unsigned char NEARDATA outbuf[BUFSZ];
  522. static unsigned short NEARDATA outbufp = 0;
  523. static short NEARDATA outrunlength = -1;
  524. static int NEARDATA bwritefd;
  525.  
  526. /*dbg()
  527. {
  528.    if(!hu) printf("outbufp %d outrunlength %d\n", outbufp,outrunlength);
  529. }*/
  530.  
  531. static void bputc(c)
  532. unsigned char c;
  533. {
  534. # ifdef DGK
  535.     bytes_counted++;
  536.     if (count_only)
  537.       return;
  538. # endif
  539.     if (outbufp >= BUFSZ) {
  540.       (void) write(bwritefd, outbuf, (int) BUFSZ);
  541.       outbufp = 0;
  542.     }
  543.     outbuf[outbufp++] = c;
  544. }
  545.  
  546. void
  547. bflush(fd)  /* flush run and buffer */
  548. register int fd;
  549. {
  550.       bwritefd = fd;
  551.       if (outrunlength >= 0) {    /* flush run */
  552.       flushoutrun(outrunlength);
  553.       }
  554.       if (outbufp) {
  555. #ifdef DGK
  556.       if (!count_only)    /* flush buffer */
  557. #endif
  558.           (void) write(fd, outbuf, outbufp);
  559.       outbufp = 0;
  560.       }
  561.       /*printf("bflush()"); getret();*/
  562. }
  563.  
  564. void
  565. bwrite(fd, loc, num)
  566. register int fd;
  567. genericptr_t loc;
  568. register unsigned num;
  569. {
  570.       bwritefd = fd;
  571.       for (; num; num--, (*(char **)&loc)++) {
  572.           if (*((char *)loc) == RLESC) { /* One more char in run */
  573.           if (++outrunlength == 0xFF) {
  574.               flushoutrun(outrunlength);
  575.           }
  576.           } else { /* end of run */
  577.           if (outrunlength >= 0) {    /* flush run */
  578.               flushoutrun(outrunlength);
  579.           }
  580.           bputc(*((char *)loc));
  581.           }
  582.       }
  583. }
  584.  
  585. #else /* ZEROCOMP */
  586.  
  587. void
  588. bwrite(fd,loc,num)
  589. register int fd;
  590. register genericptr_t loc;
  591. register unsigned num;
  592. {
  593. #ifdef DGK
  594.     bytes_counted += num;
  595.     if (!count_only)
  596. #endif
  597. /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
  598. #if defined(BSD) || defined(ULTRIX)
  599.         if(write(fd, loc, (int)num) != (int)num) {
  600. #else /* e.g. SYSV, __TURBOC__ */
  601.         if(write(fd, loc, num) != num) {
  602. #endif
  603.         if(!hu) panic("cannot write %u bytes to file #%d", num, fd);
  604.         else    exit(1);
  605.         }
  606. }
  607. #endif /* ZEROCOMP */
  608.  
  609. static void
  610. saveobjchn(fd,otmp)
  611. register int fd;
  612. register struct obj *otmp;
  613. {
  614.     register struct obj *otmp2;
  615.     unsigned int xl;
  616.     int minusone = -1;
  617.  
  618.     while(otmp) {
  619.         if(Is_container(otmp))    /* unlink contained objects */
  620.         spill_objs(otmp);    /* (this rearranges the list) */
  621.  
  622.         otmp2 = otmp->nobj;
  623.         xl = otmp->onamelth;
  624.         bwrite(fd, (genericptr_t) &xl, sizeof(int));
  625.         bwrite(fd, (genericptr_t) otmp, xl + sizeof(struct obj));
  626. #ifdef DGK
  627.         if (!count_only)
  628. #endif
  629.         free((genericptr_t) otmp);
  630.         otmp = otmp2;
  631.     }
  632.     bwrite(fd, (genericptr_t) &minusone, sizeof(int));
  633. }
  634.  
  635. static void
  636. savemonchn(fd,mtmp)
  637. register int fd;
  638. register struct monst *mtmp;
  639. {
  640.     register struct monst *mtmp2;
  641.     unsigned int xl;
  642.     int minusone = -1;
  643.     struct permonst *monbegin = &mons[0];
  644.  
  645.     bwrite(fd, (genericptr_t) &monbegin, sizeof(monbegin));
  646.  
  647.     while(mtmp) {
  648.         mtmp2 = mtmp->nmon;
  649.         xl = mtmp->mxlth + mtmp->mnamelth;
  650.         bwrite(fd, (genericptr_t) &xl, sizeof(int));
  651.         bwrite(fd, (genericptr_t) mtmp, xl + sizeof(struct monst));
  652.         if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
  653. #ifdef DGK
  654.         if (!count_only)
  655. #endif
  656.         free((genericptr_t) mtmp);
  657.         mtmp = mtmp2;
  658.     }
  659.     bwrite(fd, (genericptr_t) &minusone, sizeof(int));
  660. }
  661.  
  662. static void
  663. savegoldchn(fd,gold)
  664. register int fd;
  665. register struct gold *gold;
  666. {
  667.     register struct gold *gold2;
  668.     while(gold) {
  669.         gold2 = gold->ngold;
  670.         bwrite(fd, (genericptr_t) gold, sizeof(struct gold));
  671. #ifdef DGK
  672.         if (!count_only)
  673. #endif
  674.             free((genericptr_t) gold);
  675.         gold = gold2;
  676.     }
  677.     bwrite(fd, (genericptr_t)nulls, sizeof(struct gold));
  678. }
  679.  
  680. static void
  681. savetrapchn(fd,trap)
  682. register int fd;
  683. register struct trap *trap;
  684. {
  685.     register struct trap *trap2;
  686.     while(trap) {
  687.         trap2 = trap->ntrap;
  688.         bwrite(fd, (genericptr_t) trap, sizeof(struct trap));
  689. #ifdef DGK
  690.         if (!count_only)
  691. #endif
  692.             free((genericptr_t) trap);
  693.         trap = trap2;
  694.     }
  695.     bwrite(fd, (genericptr_t)nulls, sizeof(struct trap));
  696. }
  697.  
  698. #ifdef TUTTI_FRUTTI
  699. /* save all the fruit names and ID's; this is used only in saving whole games
  700.  * (not levels) and in saving bones levels.  When saving a bones level,
  701.  * we only want to save the fruits which exist on the bones level; the bones
  702.  * level routine marks nonexistent fruits by making the fid negative.
  703.  */
  704. void
  705. savefruitchn(fd)
  706. register int fd;
  707. {
  708.     register struct fruit *f2, *f1;
  709.  
  710.     f1 = ffruit;
  711.     while(f1) {
  712.         f2 = f1->nextf;
  713.         if (f1->fid >= 0) {
  714.             bwrite(fd, (genericptr_t) f1, sizeof(struct fruit));
  715.         }
  716. #ifdef DGK
  717.         if (!count_only)
  718. #endif
  719.             free((genericptr_t) f1);
  720.         f1 = f2;
  721.     }
  722.     bwrite(fd, (genericptr_t)nulls, sizeof(struct fruit));
  723. }
  724. #endif
  725.  
  726. static void
  727. savegenoinfo(fd)
  728. register int fd;
  729. {
  730.     register int i;
  731.  
  732.     for (i = 0; i < NUMMONS; i++)
  733.         bwrite(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned));
  734. }
  735.  
  736. #ifdef DGK
  737. boolean
  738. swapin_file(lev)
  739. int lev;
  740. {
  741.     char to[PATHLEN], from[PATHLEN];
  742.  
  743.     Sprintf(from, "%s%s", permbones, alllevels);
  744.     Sprintf(to, "%s%s", levels, alllevels);
  745.     name_file(from, lev);
  746.     name_file(to, lev);
  747.     while (fileinfo[lev].size > freediskspace(to))
  748.         if (!swapout_oldest())
  749.             return FALSE;
  750. # ifdef WIZARD
  751.     if (wizard) {
  752.         pline("Swapping in `%s'", from);
  753.         (void) fflush(stdout);
  754.     }
  755. # endif
  756.     copyfile(from, to);
  757.     (void) unlink(from);
  758.     fileinfo[lev].where = ACTIVE;
  759.     return TRUE;
  760. }
  761.  
  762. static boolean
  763. swapout_oldest() {
  764.     char to[PATHLEN], from[PATHLEN];
  765.     int i, oldest;
  766.     long oldtime;
  767.  
  768.     if (!ramdisk)
  769.         return FALSE;
  770.     for (i = 1, oldtime = 0, oldest = 0; i <= maxdlevel; i++)
  771.         if (fileinfo[i].where == ACTIVE
  772.         && (!oldtime || fileinfo[i].time < oldtime)) {
  773.             oldest = i;
  774.             oldtime = fileinfo[i].time;
  775.         }
  776.     if (!oldest)
  777.         return FALSE;
  778.     Sprintf(from, "%s%s", levels, alllevels);
  779.     Sprintf(to, "%s%s", permbones, alllevels);
  780.     name_file(from, oldest);
  781.     name_file(to, oldest);
  782. # ifdef WIZARD
  783.     if (wizard) {
  784.         pline("Swapping out `%s'.", from);
  785.         (void) fflush(stdout);
  786.     }
  787. # endif
  788.     copyfile(from, to);
  789.     (void) unlink(from);
  790.     fileinfo[oldest].where = SWAPPED;
  791.     return TRUE;
  792. }
  793.  
  794. static
  795. void
  796. copyfile(from, to)
  797. char *from, *to;
  798. {
  799. # ifdef TOS
  800.  
  801.     if (_copyfile(from, to))
  802.         panic("Can't copy %s to %s\n", from, to);
  803. # else
  804.     char buf[BUFSIZ];
  805.     int nfrom, nto, fdfrom, fdto;
  806.  
  807.     if ((fdfrom = open(from, O_RDONLY | O_BINARY, FCMASK)) < 0)
  808.         panic("Can't copy from %s !?", from);
  809.     if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK)) < 0)
  810.         panic("Can't copy to %s", to);
  811.     do {
  812.         nfrom = read(fdfrom, buf, BUFSIZ);
  813.         nto = write(fdto, buf, nfrom);
  814.         if (nto != nfrom)
  815.             panic("Copyfile failed!");
  816.     } while (nfrom == BUFSIZ);
  817.     (void) close(fdfrom);
  818.     (void) close(fdto);
  819. # endif /* TOS */
  820. }
  821. #endif
  822.  
  823. /*
  824.  * "spill" objects out of containers (unlinking from the fcobj list).
  825.  *
  826.  * The objects will be rearranged, and properly aged.  When we restore, they
  827.  * can be put back into their containers.  By the time all of the calls to
  828.  * saveobjchn() been made, the fcobj list should be empty.  Thus it need not
  829.  * be saved, and doing so could cause some strange addressing problems.
  830.  *
  831.  * NOTE:  The cobj field is set to -1.  It will be used as a flag to indicate
  832.  *      that this object was previously in a container.
  833.  */
  834.  
  835. static void
  836. spill_objs(cobj)
  837. register struct obj *cobj;
  838. {
  839.     register struct obj *otmp, *otmp2, *probj;
  840.  
  841. #if defined(LINT) || defined(__GNULINT__)
  842.     probj = (struct obj *)0;    /* suppress "used before set" error */
  843. #endif
  844.     for(otmp = fcobj; otmp; otmp = otmp2) {
  845.  
  846.         otmp2 = otmp->nobj;
  847.         if(otmp->cobj == cobj) {
  848.  
  849.         if(cobj->cursed && rn2(2))    otmp->cursed = 1;
  850.     /*
  851.      * Place all of the objects in a given container after that container
  852.      * in the list.  On restore, they should be able to be picked up and
  853.      * put back in.
  854.      */
  855.         if(otmp == fcobj) fcobj = otmp2;
  856.         else          probj->nobj = otmp2;
  857.  
  858.         otmp->nobj = cobj->nobj;
  859.         cobj->nobj = otmp;
  860.         otmp->cobj = (struct obj *)-1;
  861.         } else probj = otmp;
  862.     }
  863.  
  864. }
  865.